<?php
/**
 * Easthv Zend Framework Project
 *
 *
 * LICENSE:
 *
 * @category   Zend
 * @package    Easthv_Controller
 * @copyright  Copyright (c) 2009-2010 Easthv Team @ East Hui Van Business Consulting Co., Ltd.(http://www.easthv.com)
 * @license    http://framework.zend.com/license/   BSD License
 * @version    1.0
 * @link       http://www.easthv.com
 * @since      1.0
*/

/**
 * Class for Basic Controller.
 * All controllers will extend this controller
 * 
 * @uses       Zend_Rest_Controller
 * @category   Zend
 * @package    Easthv_Controller
 * @copyright  Copyright (c) 2009-2010 Easthv Team @ East Hui Van Business Consulting Co., Ltd.(http://www.easthv.com)
 * @license    http://framework.zend.com/license/   BSD License
 * @version    1.0
 * @link       http://www.easthv.com
 * @since      1.0
 * @deprecated
 */
abstract class Easthv_Controller_Basic extends Zend_Rest_Controller
{

    /**
     * @var array  Additional Restful resources name
     */
    public $addResources = false;

    /**
     * @var array  Current resource
     */
    protected $_resource = false;

    /**
     * @var array url params array
     */
    protected $_params;

    /**
     * @var array url params parsed by router
     */
    protected $_routerParams;

    /**
     * @var boolean whether all url params have been parsed
     */
    private $_paramsAllParsed = false;

    /**
     * @var boolean whether session has started
     */
    private $_sessionStarted = false;

    /**
     * @var boolean whether has been rendered
     */
	private $_rendered = false;


	private function _autoRouter()
	{
		$resource = $this->getResource();

        $func = 'rest' . ucfirst($resource['operate']) . $resource['resource'];
		$funcRender = $func . 'Render';
        $funcFormat = $func . ucfirst($this->_routerParams['format']);
        $funcFormatRender = $funcFormat . 'Render';

        //call function with format first
        if(true === method_exists($this, $funcFormat)) {
            $this->$funcFormat();

			return true === method_exists($this, $funcFormatRender) ? 
				$this->$funcFormatRender() : 
				$this->renderScript($this->_routerParams['controller'], $resource['render']);

        } else if(true === method_exists($this, $func)) {
            $this->$func();
			return true === method_exists($this, $funcRender) ? 
				$this->$funcRender() :
				$this->renderScript($this->_routerParams['controller'], $resource['render']);
        }

        throw new Exception('Page not found', 404);	
	}

    /**
	 * System RESTFul default interface
	 * Class method will be call by order
	 *
	 * Example: a resource product
	 * System will call by below order :
	 * restGetProductHtml
	 * restGetProductHtmlRender
	 * restGetProduct
	 * restGetProductRender
     *
     * @access public
     *
     * @return void
     */
    public function getAction()
    {
		return $this->_autoRouter();
    }

    /**
     * System RESTFul default interface
     * This method will call restIndex<ResourceName>() automatic
     *
     * @access public
     *
     * @return void
     */
    public function indexAction()
    {
		return $this->_autoRouter();
    }



    /**
     * System RESTFul interface
     *
     *
     * @access public
     *
     * @return void
     */
    public function postAction()
	{
		return $this->_autoRouter();
    }

    /**
     * System RESTFul interface
     *
     *
     * @access public
     *
     * @return void
     */
    public function putAction()
    {
		return $this->_autoRouter();
	}

	/**
	 * System RESTFul interface
	 *
	 *
	 * @access public
	 *
	 * @return void
	 */
    public function deleteAction()
	{
		return $this->_autoRouter();
    }

    /**
     * Init function defined in Zend
     * Start several functions for system initialization
     *
     * @access public
     *
     * @return void
     */
    public function init()
    {
        $this->initAll();

		if (method_exists($this, 'initCustom')) {
			$this->initCustom();
		}
    }

    /**
     * System custom init function
     * All custom init functions will be unified management here
     *
     * @access public
     *
     * @return void
     */
    public function initAll()
    {
        $this->initLayout()
            ->initSessions()
            ->initView()
			->initLanguage()
			->initUser()
			->checkPermission();
    }

    /**
     * Initialize System sessions
     * use this function , session will be Start and save into DB table
     *
     * @access public
     *
     * @return object Easthv_Controller_Basic
     */
    public function initSessions()
    {

        $config = Zend_Registry::get('config');
        if($config['system']['session']['handler'] == 'db') {
            $dbConfig = array(
                'name'             => $config['resources']['db']['prefix'] . 'sessions', //table name as per Zend_Db_Table
                'primary'         => array(
                    'session_id',   //the sessionID given by PHP
                    'save_path',    //session.save_path
                    'name',         //session name
                ),
                'primaryAssignment' => array(
                    'sessionId', //first column of the primary key is of the sessionID
                    'sessionSavePath', //second column of the primary key is the save path
                    'sessionName', //third column of the primary key is the session name
                ),
                'modifiedColumn'    => 'modified',     //time the session should expire
                'dataColumn'        => 'session_data', //serialized data
                'lifetimeColumn'    => 'lifetime',     //end of life for a specific record
			);

			if ($config['system']['cache']['enable'] && $config['system']['cache']['dbmeta'] && $config['system']['cache']['backend']['type'] == 'File') {
				$cacheType = $config['system']['cache']['backend']['type'];
				$frontendOptions = array(
					'automatic_serialization' => true
				);
				$backendOptions = array(
					'cache_dir' => APPLICATION_PATH . $config['system']['path']['cache']['dbmeta']
				);
				$cache = Zend_Cache::factory('Core', $cacheType, $frontendOptions, $backendOptions);
				Zend_Session_SaveHandler_DbTable::setDefaultMetadataCache($cache);
			}

			$saveHandler = new Zend_Session_SaveHandler_DbTable($dbConfig);
			$saveHandler->setLifetime($config['system']['session']['rememberMeSeconds'], true);
			Zend_Session::setSaveHandler($saveHandler); 
		}

		$req = $this->getParams();
		if($req['PHPSESSID']) {
			Zend_Session::setId($req['PHPSESSID']);
		}
		Zend_Session::start();

		$this->_sessionStarted = true;

		//default sessions
		$this->view->mine = $this->getSession('mine');

		//if set successHandler delay, clear success messages here
		$success = $this->getSession('success');

		if ($success) {
			$this->view->success = $success;
			$this->setSession('success',null);
		}


        return $this;
    }


    /**
     * Initialize default layout
     *
     * @param string $default   layout name to be use
     *
     * @access public
     *
     * @return object Easthv_Controller_Basic
     */
    public function initLayout($default = 'layout')
    {
		$front = Zend_Controller_Front::getInstance();
		
		$defaultModulePath = $front->getModuleDirectory('default');
		$modulePath = $front->getModuleDirectory();

		$this->_helper->layout->setLayout($default)
							  ->setLayoutPath(array($defaultModulePath . '/layouts', $modulePath . '/layouts'));
		
		return $this;
    }



    /**
     * initialize system view basic variables
     *
     * @access public
     *
     * @return object easthv_controller_basic
     */
    public function initView()
    {
        $config = Zend_Registry::get('config');

        if($config['resources']['frontController']['baseurl']) {
            $config['system']['path']['basic'] = $config['resources']['frontController']['baseurl'];
        }

        $resource = $this->getResource();

        $this->view->config = $config['system'];
        $this->view->setting = $config['system']['content'];

        $this->view->grid = array();

        $this->view->params = $this->_routerParams;

        //this will be overwrite in initLanguage
        $this->view->language = 'en';

        //change layout here if not html
        if($this->view->params['format'] != 'html') {
            $this->_helper->viewRenderer->setNoRender();
            $this->_helper->layout->setLayout($this->_routerParams['format']);
        }

		$this->view->addHelperPath(APPLICATION_PATH . '/views/helpers/');

        return $this;
    }
   
    /**
     * initialize system user variables
     *
     * @access public
     *
     * @return object easthv_controller_basic
     */
    public function initUser()
    {
        $userName = $this->getCookies('userName');
        $password = $this->getCookies('password');
        if ($userName && $password) {
            $mine = $this->getSession("mine");
            if (!$mine) {
				$user = new Easthv_Model_User();
				$userinfo = $user->find("one", array(
					'where'	=> array(
						array('userName = ?', $userName),
						array('password = ?', $password),
					)
				));

				if($userinfo){
					$mine = $user->login($userinfo['id']);
					$this->setSession('mine',$mine);
					$this->assign("mine",$mine);
				} else {
					$this->unsetCookies('userName');
					$this->unsetCookies('password');
				}
			}
		}

		return $this;
    }


    /**
     * Initialize System Language
     * Language Priority is as : User setting > Session > Browser Language > config file default setting
     *
     * @access public
     *
     * @return object Easthv_Controller_Basic
     */
    public function initLanguage()
    {

        $config = Zend_Registry::get('config');

        if (!$config['system']['i18n']['enable']) {
            $this->view->language = $config['system']['i18n']['default'] ? $config['system']['i18n']['default'] : 'en';
            return $this;
        }

        if ($config['system']['i18n']['force']) {
            $this->view->language = $config['system']['i18n']['force'];
            return $this;
        }

		$lang = $this->getSession('language');
		if (!$lang) {
			//Get language by browser
			$locale = new Zend_Locale();
			//Zend will return user main language only, eg: zh_tw => zh
			$lang = $locale->getLanguage();
			$this->setSession('language', $lang);
		}

		$this->view->language = $lang;
		return $this;

	}

	/**
     * Check User Permission
     * if user Permission is not enough , an permission error will occur
     *
     * @access public
     *
     * @return void
     */
    public function checkPermission()
    {
        $config = Zend_Registry::get('config');
		if (!$config['system']['permission']['enable']) {
			return $this;
		}

        $permission = $this->getGuestPermission();
        $resource = $this->getResource();
        $operates = array(
            'index' => 0,    
            'get' => 0,    
            'post' => 0,
            'put' => 0,
            'delete' => 0,
        );
        $operates[$resource['operate']] = 1;
        $operates = implode('',$operates);

		//module is not default
		if ($this->_routerParams['module'] != 'default') {
			$resource['resource'] = ucfirst($this->_routerParams['module']) . '_' . $resource['resource'];
		}

        if(isset($permission[$resource['resource']])) {
            $no = str_pad(decbin($permission[$resource['resource']]), 5, "0", STR_PAD_LEFT);

            // example : 11111 & 00100 = 00100
            if ( ($no & $operates) > 0) {
                return $this;
            }
        }

        //TODO: add http permission check here
        $mine = $this->getSession('mine');
        if ($mine) {
            //super admin
            if ($this->checkSuperadmin($mine) === true) {
                return $this;
            }

            $permission = $mine['Permissions'];
            if (isset($permission[$resource['resource']])) {
                $no = str_pad(decbin($permission[$resource['resource']]), 5, "0", STR_PAD_LEFT);
                if (($no & $operates) > 0) {
                    return $this;
                }
            }
        }

        throw new Exception("Permission not allow", 401);
    }

    /**
     * Check Super Admin user Permission
     *
     * @access public
     *
     * @return bool
     */
    public function checkSuperadmin($mine = null)
    {
        $mine = $mine ? $mine : $this->getSession('mine');
        $config = Zend_Registry::get('config');
        //super admin
        if ($config['system']['user']['superAdminEnable'] && $mine['id'] == $config['system']['user']['id']) {
            return true;
        }    

        return false;
    }

    /**
     * Transform Http request to a Resource Array
     * $this->_routerParams will be initialize here too
     *
     * @access public
     *
     * @return array  resource array
     */
    public function getResource()
    {
        if ($this->_resource !== false) {
            return $this->_resource;
        }

		if($this->additionalRequests) {
			$this->_routerParams = $param = array_diff_key($this->getParams(), $this->additionalRequests);
		} else {
			$this->_routerParams = $param = $this->getParams();
		}
        $render = $param['action'];

        $resource = ucfirst($param['controller']);

        if ($this->addResources !== false && ($param['action'] == 'get' || $param['action'] == 'put' || $param['action'] == 'delete')) {

            //url like /posts/abc
            if (isset($param['id']) && $param['id'] && in_array($param['id'],$this->addResources)) {
                $resource .= ucfirst($param['id']);
                $render = $param['id'];
            }

            //url like /posts/abc/123 or /posts/abc/123/def/456
            if (!isset($param['id']) || !$param['id']) {

                $render = '';

                //check the param id whether in addResources
                $params = array_intersect_key($param, array_flip($this->addResources));

                //url like /posts/abc/123/def/456 , "abc" and "def" are both addResources
                if (count($params) > 1) {
                    //order params by array key
                    ksort($params);
                }

                foreach($params as $key => $_param){
                    $resource .= ucfirst($key);
                    $render .= $key;
                }
                
				if(!$render) {
					$render = 'get';
				}
            
            }
        }

        $this->_routerParams['resource'] = $resource;
        return $this->_resource = array(
            'operate' => $param['action'],
            'resource' => $resource,
            'render' => $render,
        );
    
    }

    /**
     * Get permission of system guest user
     *
     * @access public
     *
     * @return array permission array
     */
    public function getGuestPermission()
    {
        $config = Zend_Registry::get('config');

        //permission cache enable
        if ($config['system']['cache']['permission']) {
            $path = APPLICATION_PATH . $config['system']['path']['cache']['permission'] . 'guest.cache';
            if(file_exists($path)) {
                return unserialize(file_get_contents($path));
            }        
        }

        if (!$config['system']['user']['guestId']) {
            throw new Exception("Not set system guest role");
        }

        $role = new Easthv_Model_User_Role();
		$role = $role->getPermissionsByRoleId($config['system']['user']['guestId']);

        //create cache here is cache file not exist
        if ($config['system']['cache']['permission']) {
            Zend_Easthv_File::writeFile($path,serialize($role['Permissions']) );
        }

        return $role['Permissions'];
    }

    /**
     * Set System session
     * Save input data into session
     *
     * @param string $key   session name to be set
     * @param mixed $value   this param can be any data type
     * @param boolean $encode whether encode session value
     *
     *
     * @access public
     *
     * @return object Easthv_Controller_Basic
     */
    public function setSession($key, $value, $encode = false)
    {

        $this->_sessionStarted === false ? $this->initSessions() : null;

        $session = new Zend_Session_Namespace('Easthv');

        $session->$key = $encode === false ? $value : base64_encode(serialize($value));

        return $this;

    }

    /**
     * Get System session
     *
     * @param string $key   session name to be get
     * @param boolean $encode whether decode session value
     *
     * @access public
     *
     * @return array sessions array
     */
    public function getSession($key = null, $decode = false)
    {

        $this->_sessionStarted === false ? $this->initSessions() : null;

        $session = new Zend_Session_Namespace('Easthv');

        return $key ? ($decode === false ? $session->$key : base64_decode(unserialize($session->$key))) : $session;
    }

    /**
     * Set System cookies
     * Save input data into cookies
     *
     * @param string $key   cookie name to be set
     * @param mixed $value   this param can be any data type
     * @param int   $expire  expire seconds
     *
     * @access public
     *
     * @return boolean set cookie result
     */
    public function setCookies($key,$value = null,$expire = null)
    {
        $config = Zend_Registry::get('config');
        $expire = $expire ? time() + $expire : time() + (int)$config['system']['session']['rememberMeSeconds'];
        return setrawcookie($key,base64_encode(gzcompress(serialize($value))),$expire,"/");

    }

    /**
     * Unset System cookies
     *
     * @param string $key   cookie name to be unset
     *
     * @access public
     *
     * @return void
     */
    public function unsetCookies($key)
    {

        setrawcookie($key,null,-1,'/');
        unset($_COOKIE[$key]);

    }


    /**
     * Get System cookie
     *
     * @param string $key  cookie name to be get
     *
     * @access public
     *
     * @return mixed cookie data
     */
    public function getCookies($key = null)
    {

        if($key) {
            return isset($_COOKIE[$key]) && $_COOKIE[$key] ? unserialize(gzuncompress(base64_decode($_COOKIE[$key]))) : '';
        }
        $res = array();
        foreach($_COOKIE as $key => $value) {
            if (!isset($_COOKIE[$key]) && $_COOKIE[$key]) {
                continue;
            }
            $res[$key] = unserialize(gzuncompress(base64_decode($value)));
        }

        return $res;
    }
    
    /**
     * 
     *
     * 
     *
     * @access public
     *
     * @return string
     */
    public function saveReferer()
    {
        return $_SERVER['HTTP_REFERER'];
    }


    /**
     * Get Current Full Url
     *
     * @param boolean $withQuery  whether with url QUERY_STRING
     * 
     * @access public
     *
     * @return string Current url string
     */
    public function getCurrentUrl($withQuery = true)
    {
        return $this->view->Easy()->getCurrentUrl($withQuery);
    }

    /**
     * Keep some url params to view
     *
     * @param string   if params exist, function will catch system request only in params
     *                 if params not exist, function will catch all system request
     * @access public
     *
     * @return array   system request array
     */
    public function keepParams()
    {
        $params = func_get_args();
        array_push($params,'page','order','sortby');

        $res = array();
        foreach($params as $param) {

            $tmp = $this->getParams($param);
            //remove empty param
            if (!$tmp || !$tmp[$param]) {
                continue;
            }
            $this->view->grid[$param] = $tmp[$param];

        }

        //sort by key
        return $this->view->grid ? ksort($this->view->grid) : array();
    
    }

    /**
     * Mapping a url param key to database field name
     *
     * @param string $param   url param
     * @param array  $fields  database fields mapping array
     *
     * @return string database field name
     */
    public function mappingOne($param,$filelds)
    {
        $filelds = array_flip($filelds);
        return isset($filelds[$param]) ? $filelds[$param] : '';    
    }

    /**
     * Mapping an array to database fields array by array key name
     *
     * @param array $params   array to be mapping
     * @param array $fields   database fields mapping array
     *
     * @return array   database fields array
     */
    public function mappingAll($params,$fields)
    {
        $res = array();

        foreach($fields as $dbfield => $paramName) {
			if (!isset($params[$paramName])) {
				continue;
			}
            $res[$dbfield] = $params[$paramName];

        }
        return $res;    
    }

    /**
     * Get System Request by using Zend Controller function controller->_request->get
     *
     * @param string   if params exist, function will catch system request only in params
     *                 if params not exist, function will catch all system request
     * @access public
     *
     * @return array   system request array
     */
    public function getParams()
    {
        if (0 == func_num_args()) {
            if ($this->_paramsAllParsed === false) {
                //if all url params saved into $this->_params
                $this->_paramsAllParsed = true;
                return $this->_params = $this->_request->getParams();
            } else {
                return $this->_params;
            }
        }


        $params = func_get_args();

        $res = array();

        foreach($params as $param) {

            if (isset($this->_params[$param])) {

                $res[$param] = $this->_params[$param];

            } else {

                $res[$param] = $this->_request->get($param);

                $res[$param] = is_array($res[$param]) ? $res[$param] : trim($res[$param]);

                $this->_params[$param] = $res[$param];            
            }

        }

        return $res;
    }


    /**
     * This function can escape every param in array which user input
     *
     *
     * @param mixed $values  input data to be escape
     *
     * @access public
     *
     * @return mixed   escaped data
     */
    public function escapes($values)
    {

        if (is_array($values)) {

            $res = array();

            foreach($values as $key => $value) {

                if (is_array($value)) {

                    $res[$key] = $this->escapes($value);

                } else {

                    $res[$key] = $value ? $this->view->escape($value) : '';
                }


            }

            return $res;

        } else {

            return $this->view->escape((string)$values);

        }
    }

    /**
     * Set param to View
     * This function will set data into system view, and data will all be escaped
     * suggest using this function to instead of $this->view->escape function
     *
     * @param string $spec  View param name
     * @param mixed $value  data to be set
     *
     *
     * @access public
     *
     * @return object $this
     */
    public function assign($spec,$value,$noEscape = false)
    {

        $this->view->$spec = $noEscape === false ? $this->escapes($value) : $value;

        return $this;

    }

    /**
     * override render function for i18n
     *
     *
     * @param string   $template  view template name
     *
     * @access public
     *
     * @return void
     */
    public function render($template = null,$name = null,$noController = false,$forceRender = false)
    {
        if ($this->_rendered === true && $forceRender === false) {
            return;
        }

        $this->view->render = $template;
        $this->_rendered = true;
        parent::render($template,$name,$noController);
    }

    /**
     * override render function for i18n
     *
     *
     * @param string   $template  view template name
     *
     * @access public
     *
     * @return void
     */
    public function renderScript($controller , $action , $forceRender = false)
    {
        if ($this->_rendered === true && $forceRender === false) {
            return;
        }

        $this->_rendered = true;
        parent::renderScript($controller . '/' . $action . '.phtml');
    }

    /**
     * This function accept validation failed messages and send them to View
     * You can use this function once in a controller
     * or else the validation messages will be overlay
     *
     *
     * @param array   validation messages
     *
     * @access public
     *
     * @return object $this
     */
    public function validHandler()
    {
        if (0 == func_num_args()) {
            return;
        }

        $valids = func_get_args();

        $this->_routerParams['format'] != 'html' ? $this->initLayout($this->_routerParams['format']) : '';
        $this->view->valids = Zend_Easthv_Validate::cleanMessages($valids);
	}

    /**
     * Redirect to a url
     * if there is a url param with the name as same as $param , this url will be redirected first
     *
     * @param string $to     redirect url
     * @param string $param  url param name for redirecting
     *
     * @access public
     *
     * @return void
     */
    public function redirect($to = null, $param = 'jumpto', $byMeta = false)
    {

        if ($this->_routerParams['format'] != 'html') {
            return;
        }

        $jumpto = $this->getParams($param);
        $jumpto = $jumpto[$param];

        //if there is 'jumpto' in url param, redirect this first
        $to = $jumpto ? $jumpto : $to;


        //not set any redirect
        if (!$to) {
            return false;
        }

        //decode jumpto
        if ($jumpto) {
            
            //TODO: if debug, do not decode
            $to = gzuncompress(base64_decode( str_replace("-", "/", str_replace("*", "+", $to ) ) ));
        }

        //if set redirectDelay, not redirect at controller
		if ($byMeta !== false) {
			$delay = is_numeric($byMeta) ? $byMeta : $this->view->redirectDelay;
			$this->view->redirectDelay = $delay;
            return $this->view->redirect = $to;
        }

        return $this->_redirect($to);
    
    }

    /**
     * This function will handler mvc errors and print out errors messages
     * for changing errors show way , you should change system layout
     *
     *
     * @param string $error       error messages title
     * @param string $errorLevel  error level (Normal or Warning)
     *                            if is Normal, user can only see error messages
     *                            if is Warning , page elements will be print out too
     * @param string $errorTpl    use custom error messages template
     *
     * @access public
     *
     * @return void
     */
    public function errorHandler($error = null, $additions = null)
    {

        if (!$error) {
            throw new Exception('Nothing input to errorHandler');
        }


        $this->_routerParams['format'] != 'html' ? $this->initLayout($this->_routerParams['format']) : '';

        $errorType = gettype($error);

        switch($errorType) {
            
        case 'object' :
            $errors = array(
                'code' => isset($additions['code']) ? $additions['code'] : 500,
                'message' => $error->getMessage(),
                'template' => is_string($additions) ? $additions : ($additions['template'] ? $additions['template'] : 'default'),
                'showContent' => isset($additions['showContent']) ? $additions['showContent'] : true,
            );
            break;

        case 'string' :
            $errors = array(
                'code' => $additions['code'] ? $additions['code'] : 500,
                'message' => $error,
                'template' => is_string($additions) ? $additions : ($additions['template'] ? $additions['template'] : 'default'),
                'showContent' => isset($additions['showContent']) ? $additions['showContent'] : true,
            );
            break;

        default : 

            $errors = array(
                'code' => $error['code'] ? $error['code'] : 500,
                'message' => $error['message'],
                'template' => $error['template'] ? $error['template'] : 'default',
                'showContent' => isset($error['showContent']) ? $error['showContent'] : true,
            );

            break;

        }

        if ($errors['code'] != 500) {
            $this->getResponse()->setHttpResponseCode($errors['code'])->setRawHeader($errors['messages']);
        }

        return $this->view->errors = $errors;

    }

    /**
     * This function will show help messages to user
     *
     * @param string $tpl    use custom help messages template
     *
     * @access public
     *
     * @return void
     */
    public function hintHandler($hint =null, $additions = null)
    {

        if (!$hint) {
            return $this;
        }
        
        $hintType = gettype($hint);

        $additions = is_array($additions) ? $additions : array(
            'template' => $additions ? $additions : 'default',
        );
        
        switch ($hintType) {
            
        case 'string' :
            $hints = array(
                'message' => $hint,
                'template' => $additions['template'] ? $additions['template'] : 'default',
            );
            break;

        default : 

            $hints = array(
                'message' => $hint['message'],
                'template' => $hint['template'] ? $hint['template'] : 'default',
            );

            break;

        }

        $this->view->hint = $hints;

    }

    /**
     * This function will show success messages and redirect user to other page
     * for changing success messages show way , you should change system layout
     *
     * @param string $msg           success messages
     * @param string $redirect      redirect url
     *                              if not set , page will not be redirect
     * @param string $successLevel  success level(Normal or Remind or Redirect or Delay)
     *                              if is Normal, user can only see success messages
     *                              if is Remind, page elements will be print out too                             
     *                              if is Redirect, page will be redirect will no messages
     *                              if is Delay, page will be redirect, success messages will show after redirect
     *
     * @access public
     *
     * @return void
     */
    public function successHandler($succ = null, $additions = null)
    {
        if (!$succ) {
            throw new Exception('Nothing input to successHandler');
        }

        $this->_routerParams['format'] != 'html' ? $this->initLayout($this->_routerParams['format']) : '';

        $successType = gettype($succ);

        $additions = is_array($additions) ? $additions : array(
            'code' => 200,
            'template' => 'default',
            'redirect' => $additions,
            'showContent' => true,
            'delay' => true,
        );

        switch ($successType) {
            
        case 'object' :
            $success = array(
                'code' => $additions['code'] ? $additions['code'] : 200,
                'message' => $succ->getMessage(),
                'template' => $additions['template'] ? $additions['template'] : 'default',
                'redirect' => is_string($additions) ? $additions : $additions['redirect'],
                'showContent' => isset($additions['showContent']) ? $additions['showContent'] : true,
                'delay' => isset($additions['delay']) ? $additions['delay'] : true,
            );
            break;

        case 'string' :
            $success = array(
                'code' => isset($additions['code']) ? $additions['code'] : 200,
                'message' => $succ,
                'template' => $additions['template'] ? $additions['template'] : 'default',
                'redirect' => is_string($additions) ? $additions : $additions['redirect'],
                'showContent' => isset($additions['showContent']) ? $additions['showContent'] : true,
                'delay' => isset($additions['delay']) ? $additions['delay'] : true,
            );
            break;

        default : 

            $success = array(
                'code' => $success['code'] ? $success['code'] : 200,
                'message' => $succ['message'],
                'template' => $succ['template'] ? $succ['template'] : 'default',
                'redirect' => $succ['redirect'],
                'showContent' => isset($succ['showContent']) ? $succ['showContent'] : true,
                'delay' => isset($succ['delay']) ? $succ['delay'] : true,
            );

            break;

        }

        if ($success['code'] != 200) {
            $this->getResponse()->setHttpResponseCode($success['code']);
        }

        $this->view->success = $success;

        //only save success to session when html
        if ($success['delay'] === true && $this->_routerParams['format'] == 'html') {
            if ($this->_sessionStarted === false) {
                $this->initSessions();
            }
            $this->setSession('success',$success);
        }

        $this->redirect($success['redirect']);

        return $this->view->success = $success;
    }

}
